////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008 Michiel Helvensteijn                                    //
//                                                                            //
// This file is part of the Mist compiler.                                    //
//                                                                            //
// The Mist compiler is free software: you can redistribute it and/or modify  //
// it under the terms of the GNU General Public License as published by       //
// the Free Software Foundation, either version 3 of the License, or          //
// (at your option) any later version.                                        //
//                                                                            //
// The Mist compiler is distributed in the hope that it will be useful,       //
// but WITHOUT ANY WARRANTY; without even the implied warranty of             //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              //
// GNU General Public License for more details.                               //
//                                                                            //
// You should have received a copy of the GNU General Public License          //
// along with the Mist compiler.  If not, see <http://www.gnu.org/licenses/>. //
////////////////////////////////////////////////////////////////////////////////

#include "expressionnavigator.hpp"

/******************************************************************************
 * Includes                                                                   *
 ******************************************************************************/

#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH

#include "ast/nodetypes.hpp"
#include "assert.hpp"

/******************************************************************************
 * Function Implementations                                                   *
 ******************************************************************************/

void ExpressionNavigator::visit(shared_ptr<ArithmeticOperation> node) {
	assert(node);
	
	node->left_operand()->accept(shared_from_this());
	node->right_operand()->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<FunctionCall> node) {
	assert(node);
	
	node->base()->accept(shared_from_this());
	foreach (shared_ptr<Expression> parameter, node->parameters())
		parameter->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<UnaryOperation> node) {
	assert(node);
	
	node->operand()->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<Assertion> node) {
	assert(node);
	
	if (node->condition_is_set())
		node->condition()->accept(shared_from_this());
	else
		node->variable_declaration()->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<Assignment> node) {
	assert(node);
	
	node->left_side()->accept(shared_from_this());
	node->right_side()->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<IdAssignment> node) {
	assert(node);
	
	node->left_side()->accept(shared_from_this());
	node->right_side()->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<VariableDeclaration> node) {
	assert(node);
	
	foreach (VarDec var, node->variables())
		if (var.is_initialized())
			var.init->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<Subscripting> node) {
	assert(node);
	
	node->base()->accept(shared_from_this());
	node->subscript()->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<ComparisonChain> node) {
	assert(node);
	
	foreach (shared_ptr<Expression> operand, node->operands())
		operand->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<IfStatement> node) {
	assert(node);
	
	node->condition()->accept(shared_from_this());
	StatementNavigator::visit(node);
}

void ExpressionNavigator::visit(shared_ptr<WhileStatement> node) {
	assert(node);
	
	node->condition()->accept(shared_from_this());
	StatementNavigator::visit(node);
}

void ExpressionNavigator::visit(shared_ptr<AndChain> node) {
	assert(node);
	
	foreach (shared_ptr<Expression> operand, node->operands())
		operand->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<OrChain> node) {
	assert(node);
	
	foreach (shared_ptr<Expression> operand, node->operands())
		operand->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<ImpliesChain> node) {
	assert(node);
	
	foreach (shared_ptr<Expression> operand, node->operands())
		operand->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<ForStatement> node) {
	assert(node);
	
	node->range()->accept(shared_from_this());
	StatementNavigator::visit(node);
}

void ExpressionNavigator::visit(shared_ptr<Range> node) {
	assert(node);
	
	node->lower_bound()->accept(shared_from_this());
	node->upper_bound()->accept(shared_from_this());
	node->step()->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<BooleanPointerLiteral> node) {
	assert(node);
	
	node->value()->accept(shared_from_this());
}

void ExpressionNavigator::visit(shared_ptr<IntegerPointerLiteral> node) {
	assert(node);
	
	node->value()->accept(shared_from_this());
}
